<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2048小游戏</title>
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        .game-container {
            position: relative;
            background: #bbada0;
            border-radius: 10px;
            width: 500px;
            height: 500px;
            margin: 0 auto;
            padding: 15px;
            box-sizing: border-box;
        }
        
        .grid-container {
            position: absolute;
            z-index: 1;
        }
        
        .grid-row {
            margin-bottom: 15px;
        }
        
        .grid-row:last-child {
            margin-bottom: 0;
        }
        
        .grid-cell {
            width: 107px;
            height: 107px;
            background: rgba(238, 228, 218, 0.35);
            border-radius: 6px;
            margin-right: 15px;
            float: left;
        }
        
        .grid-cell:last-child {
            margin-right: 0;
        }
        
        .tile-container {
            position: absolute;
            z-index: 2;
        }
        
        .tile {
            width: 107px;
            height: 107px;
            background: #eee4da;
            border-radius: 6px;
            font-weight: bold;
            text-align: center;
            line-height: 107px;
            font-size: 55px;
            position: absolute;
            transition: all 0.15s ease-in-out;
        }
        
        .tile-2 { background: #eee4da; color: #776e65; }
        .tile-4 { background: #ede0c8; color: #776e65; }
        .tile-8 { background: #f2b179; color: #f9f6f2; }
        .tile-16 { background: #f59563; color: #f9f6f2; }
        .tile-32 { background: #f67c5f; color: #f9f6f2; }
        .tile-64 { background: #f65e3b; color: #f9f6f2; }
        .tile-128 { background: #edcf72; color: #f9f6f2; font-size: 45px; }
        .tile-256 { background: #edcc61; color: #f9f6f2; font-size: 45px; }
        .tile-512 { background: #edc850; color: #f9f6f2; font-size: 45px; }
        .tile-1024 { background: #edc53f; color: #f9f6f2; font-size: 35px; }
        .tile-2048 { background: #edc22e; color: #f9f6f2; font-size: 35px; }
        
        .tile-super { background: #3c3a32; color: #f9f6f2; font-size: 30px; }
        
        .game-message {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(255, 255, 255, 0.9);
            border-radius: 10px;
            display: none;
            align-items: center;
            justify-content: center;
            flex-direction: column;
            z-index: 100;
        }
        
        .game-message.game-won {
            background: rgba(237, 194, 46, 0.9);
            color: #f9f6f2;
        }
        
        .game-message.game-over {
            background: rgba(238, 228, 218, 0.9);
            color: #776e65;
        }
        
        .clearfix::after {
            content: "";
            display: table;
            clear: both;
        }
        
        @keyframes appear {
            0% {
                opacity: 0;
                transform: scale(0);
            }
            100% {
                opacity: 1;
                transform: scale(1);
            }
        }
        
        .tile-new {
            animation: appear 0.2s ease-in-out;
        }
        
        @keyframes pop {
            0% {
                transform: scale(1);
            }
            50% {
                transform: scale(1.2);
            }
            100% {
                transform: scale(1);
            }
        }
        
        .tile-merged {
            animation: pop 0.2s ease-in-out;
        }
    </style>
</head>
<body class="bg-gray-100 min-h-screen">
    <div class="container mx-auto px-6 py-8">
        <div class="max-w-4xl mx-auto">
            <!-- 标题和说明 -->
            <div class="text-center mb-8">
                <h1 class="text-4xl font-bold text-gray-800 mb-4">
                    <i class="fas fa-gamepad text-blue-500 mr-3"></i>
                    2048小游戏
                </h1>
                <p class="text-gray-600 mb-4">使用方向键移动方块，相同数字的方块会合并！</p>
                <div class="bg-blue-50 border border-blue-200 rounded-lg p-4 inline-block">
                    <p class="text-blue-800 text-sm">
                        <i class="fas fa-info-circle mr-2"></i>
                        <strong>游戏规则：</strong>使用键盘方向键或WASD键移动方块，当两个相同数字的方块碰撞时会合并成一个更大的数字。目标是创造出2048方块！
                    </p>
                </div>
            </div>
            
            <!-- 游戏控制面板 -->
            <div class="bg-white rounded-lg shadow-lg p-6 mb-6">
                <div class="flex flex-wrap justify-between items-center gap-4">
                    <div class="flex gap-6">
                        <div class="text-center">
                            <div class="text-2xl font-bold text-blue-600" id="score">0</div>
                            <div class="text-sm text-gray-600">得分</div>
                        </div>
                        <div class="text-center">
                            <div class="text-2xl font-bold text-green-600" id="best">0</div>
                            <div class="text-sm text-gray-600">最高分</div>
                        </div>
                        <div class="text-center">
                            <div class="text-2xl font-bold text-purple-600" id="moves">0</div>
                            <div class="text-sm text-gray-600">移动次数</div>
                        </div>
                    </div>
                    
                    <div class="flex gap-3">
                        <button onclick="newGame()" class="bg-blue-600 text-white px-6 py-2 rounded-lg hover:bg-blue-700 transition-colors">
                            <i class="fas fa-play mr-2"></i>新游戏
                        </button>
                        <button onclick="undoMove()" class="bg-yellow-600 text-white px-6 py-2 rounded-lg hover:bg-yellow-700 transition-colors" id="undoBtn">
                            <i class="fas fa-undo mr-2"></i>撤销
                        </button>
                        <button onclick="togglePause()" class="bg-green-600 text-white px-6 py-2 rounded-lg hover:bg-green-700 transition-colors" id="pauseBtn">
                            <i class="fas fa-pause mr-2"></i>暂停
                        </button>
                    </div>
                </div>
            </div>
            
            <!-- 游戏区域 -->
            <div class="flex justify-center mb-6">
                <div class="game-container" id="gameContainer">
                    <div class="grid-container">
                        <div class="grid-row clearfix">
                            <div class="grid-cell"></div>
                            <div class="grid-cell"></div>
                            <div class="grid-cell"></div>
                            <div class="grid-cell"></div>
                        </div>
                        <div class="grid-row clearfix">
                            <div class="grid-cell"></div>
                            <div class="grid-cell"></div>
                            <div class="grid-cell"></div>
                            <div class="grid-cell"></div>
                        </div>
                        <div class="grid-row clearfix">
                            <div class="grid-cell"></div>
                            <div class="grid-cell"></div>
                            <div class="grid-cell"></div>
                            <div class="grid-cell"></div>
                        </div>
                        <div class="grid-row clearfix">
                            <div class="grid-cell"></div>
                            <div class="grid-cell"></div>
                            <div class="grid-cell"></div>
                            <div class="grid-cell"></div>
                        </div>
                    </div>
                    
                    <div class="tile-container" id="tileContainer"></div>
                    
                    <div class="game-message" id="gameMessage">
                        <div class="text-center">
                            <h2 class="text-4xl font-bold mb-4" id="messageTitle"></h2>
                            <p class="text-lg mb-6" id="messageText"></p>
                            <button onclick="newGame()" class="bg-blue-600 text-white px-8 py-3 rounded-lg hover:bg-blue-700 transition-colors text-lg">
                                <i class="fas fa-play mr-2"></i>再来一局
                            </button>
                        </div>
                    </div>
                </div>
            </div>
            
            <!-- 移动端控制按钮 -->
            <div class="block md:hidden">
                <div class="bg-white rounded-lg shadow-lg p-6">
                    <h3 class="text-lg font-semibold text-gray-800 mb-4 text-center">移动控制</h3>
                    <div class="grid grid-cols-3 gap-2 max-w-xs mx-auto">
                        <div></div>
                        <button onclick="move('up')" class="bg-gray-200 hover:bg-gray-300 p-4 rounded-lg transition-colors">
                            <i class="fas fa-arrow-up text-2xl"></i>
                        </button>
                        <div></div>
                        <button onclick="move('left')" class="bg-gray-200 hover:bg-gray-300 p-4 rounded-lg transition-colors">
                            <i class="fas fa-arrow-left text-2xl"></i>
                        </button>
                        <div class="bg-gray-100 rounded-lg flex items-center justify-center">
                            <i class="fas fa-hand-pointer text-gray-400"></i>
                        </div>
                        <button onclick="move('right')" class="bg-gray-200 hover:bg-gray-300 p-4 rounded-lg transition-colors">
                            <i class="fas fa-arrow-right text-2xl"></i>
                        </button>
                        <div></div>
                        <button onclick="move('down')" class="bg-gray-200 hover:bg-gray-300 p-4 rounded-lg transition-colors">
                            <i class="fas fa-arrow-down text-2xl"></i>
                        </button>
                        <div></div>
                    </div>
                </div>
            </div>
            
            <!-- 游戏统计 -->
            <div class="mt-6 grid grid-cols-1 md:grid-cols-3 gap-4">
                <div class="bg-white rounded-lg shadow-sm border border-gray-200 p-4">
                    <h4 class="font-semibold text-gray-800 mb-2">游戏进度</h4>
                    <div class="space-y-2">
                        <div class="flex justify-between">
                            <span class="text-sm text-gray-600">最大方块:</span>
                            <span class="text-sm font-semibold" id="maxTile">2</span>
                        </div>
                        <div class="flex justify-between">
                            <span class="text-sm text-gray-600">空格数:</span>
                            <span class="text-sm font-semibold" id="emptyCells">14</span>
                        </div>
                        <div class="flex justify-between">
                            <span class="text-sm text-gray-600">游戏时间:</span>
                            <span class="text-sm font-semibold" id="gameTime">00:00</span>
                        </div>
                    </div>
                </div>
                
                <div class="bg-white rounded-lg shadow-sm border border-gray-200 p-4">
                    <h4 class="font-semibold text-gray-800 mb-2">操作提示</h4>
                    <div class="space-y-1 text-sm text-gray-600">
                        <div><i class="fas fa-keyboard mr-2"></i>方向键或WASD移动</div>
                        <div><i class="fas fa-undo mr-2"></i>Ctrl+Z 撤销操作</div>
                        <div><i class="fas fa-play mr-2"></i>R键重新开始</div>
                        <div><i class="fas fa-pause mr-2"></i>空格键暂停游戏</div>
                    </div>
                </div>
                
                <div class="bg-white rounded-lg shadow-sm border border-gray-200 p-4">
                    <h4 class="font-semibold text-gray-800 mb-2">成就系统</h4>
                    <div class="space-y-2">
                        <div class="flex items-center justify-between">
                            <span class="text-sm text-gray-600">达到512</span>
                            <i class="fas fa-trophy text-yellow-500" id="achievement512" style="opacity: 0.3;"></i>
                        </div>
                        <div class="flex items-center justify-between">
                            <span class="text-sm text-gray-600">达到1024</span>
                            <i class="fas fa-trophy text-yellow-500" id="achievement1024" style="opacity: 0.3;"></i>
                        </div>
                        <div class="flex items-center justify-between">
                            <span class="text-sm text-gray-600">达到2048</span>
                            <i class="fas fa-crown text-yellow-500" id="achievement2048" style="opacity: 0.3;"></i>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
    <script>
        class Game2048 {
            constructor() {
                this.grid = [];
                this.score = 0;
                this.moves = 0;
                this.best = localStorage.getItem('2048-best') || 0;
                this.gameState = 'playing'; // playing, won, over, paused
                this.history = [];
                this.startTime = null;
                this.gameTimer = null;
                this.isPaused = false;
                
                this.init();
                this.setupEventListeners();
                this.updateDisplay();
            }
            
            init() {
                // 初始化4x4网格
                this.grid = [];
                for (let i = 0; i < 4; i++) {
                    this.grid[i] = [0, 0, 0, 0];
                }
                
                // 添加两个初始方块
                this.addRandomTile();
                this.addRandomTile();
                
                this.score = 0;
                this.moves = 0;
                this.gameState = 'playing';
                this.history = [];
                this.startTime = Date.now();
                this.isPaused = false;
                
                this.startTimer();
                this.saveState();
            }
            
            setupEventListeners() {
                document.addEventListener('keydown', (e) => {
                    if (this.gameState === 'paused') return;
                    
                    switch(e.key) {
                        case 'ArrowUp':
                        case 'w':
                        case 'W':
                            e.preventDefault();
                            this.move('up');
                            break;
                        case 'ArrowDown':
                        case 's':
                        case 'S':
                            e.preventDefault();
                            this.move('down');
                            break;
                        case 'ArrowLeft':
                        case 'a':
                        case 'A':
                            e.preventDefault();
                            this.move('left');
                            break;
                        case 'ArrowRight':
                        case 'd':
                        case 'D':
                            e.preventDefault();
                            this.move('right');
                            break;
                        case 'r':
                        case 'R':
                            this.newGame();
                            break;
                        case ' ':
                            e.preventDefault();
                            this.togglePause();
                            break;
                    }
                    
                    if (e.ctrlKey && e.key === 'z') {
                        e.preventDefault();
                        this.undoMove();
                    }
                });
            }
            
            addRandomTile() {
                const emptyCells = [];
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        if (this.grid[i][j] === 0) {
                            emptyCells.push({x: i, y: j});
                        }
                    }
                }
                
                if (emptyCells.length > 0) {
                    const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
                    this.grid[randomCell.x][randomCell.y] = Math.random() < 0.9 ? 2 : 4;
                }
            }
            
            move(direction) {
                if (this.gameState !== 'playing') return;
                
                this.saveState();
                
                let moved = false;
                const newGrid = this.grid.map(row => [...row]);
                
                switch(direction) {
                    case 'left':
                        moved = this.moveLeft(newGrid);
                        break;
                    case 'right':
                        moved = this.moveRight(newGrid);
                        break;
                    case 'up':
                        moved = this.moveUp(newGrid);
                        break;
                    case 'down':
                        moved = this.moveDown(newGrid);
                        break;
                }
                
                if (moved) {
                    this.grid = newGrid;
                    this.addRandomTile();
                    this.moves++;
                    this.updateDisplay();
                    this.checkGameState();
                }
            }
            
            moveLeft(grid) {
                let moved = false;
                for (let i = 0; i < 4; i++) {
                    const row = grid[i].filter(val => val !== 0);
                    for (let j = 0; j < row.length - 1; j++) {
                        if (row[j] === row[j + 1]) {
                            row[j] *= 2;
                            this.score += row[j];
                            row.splice(j + 1, 1);
                        }
                    }
                    while (row.length < 4) {
                        row.push(0);
                    }
                    
                    for (let j = 0; j < 4; j++) {
                        if (grid[i][j] !== row[j]) {
                            moved = true;
                        }
                        grid[i][j] = row[j];
                    }
                }
                return moved;
            }
            
            moveRight(grid) {
                let moved = false;
                for (let i = 0; i < 4; i++) {
                    const row = grid[i].filter(val => val !== 0);
                    for (let j = row.length - 1; j > 0; j--) {
                        if (row[j] === row[j - 1]) {
                            row[j] *= 2;
                            this.score += row[j];
                            row.splice(j - 1, 1);
                            j--;
                        }
                    }
                    while (row.length < 4) {
                        row.unshift(0);
                    }
                    
                    for (let j = 0; j < 4; j++) {
                        if (grid[i][j] !== row[j]) {
                            moved = true;
                        }
                        grid[i][j] = row[j];
                    }
                }
                return moved;
            }
            
            moveUp(grid) {
                let moved = false;
                for (let j = 0; j < 4; j++) {
                    const column = [];
                    for (let i = 0; i < 4; i++) {
                        if (grid[i][j] !== 0) {
                            column.push(grid[i][j]);
                        }
                    }
                    
                    for (let i = 0; i < column.length - 1; i++) {
                        if (column[i] === column[i + 1]) {
                            column[i] *= 2;
                            this.score += column[i];
                            column.splice(i + 1, 1);
                        }
                    }
                    
                    while (column.length < 4) {
                        column.push(0);
                    }
                    
                    for (let i = 0; i < 4; i++) {
                        if (grid[i][j] !== column[i]) {
                            moved = true;
                        }
                        grid[i][j] = column[i];
                    }
                }
                return moved;
            }
            
            moveDown(grid) {
                let moved = false;
                for (let j = 0; j < 4; j++) {
                    const column = [];
                    for (let i = 0; i < 4; i++) {
                        if (grid[i][j] !== 0) {
                            column.push(grid[i][j]);
                        }
                    }
                    
                    for (let i = column.length - 1; i > 0; i--) {
                        if (column[i] === column[i - 1]) {
                            column[i] *= 2;
                            this.score += column[i];
                            column.splice(i - 1, 1);
                            i--;
                        }
                    }
                    
                    while (column.length < 4) {
                        column.unshift(0);
                    }
                    
                    for (let i = 0; i < 4; i++) {
                        if (grid[i][j] !== column[i]) {
                            moved = true;
                        }
                        grid[i][j] = column[i];
                    }
                }
                return moved;
            }
            
            checkGameState() {
                // 检查是否获胜
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        if (this.grid[i][j] === 2048 && this.gameState === 'playing') {
                            this.gameState = 'won';
                            this.showMessage('恭喜获胜！', '你成功达到了2048！');
                            this.unlockAchievement(2048);
                            return;
                        }
                    }
                }
                
                // 检查是否还有空格
                let hasEmptyCell = false;
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        if (this.grid[i][j] === 0) {
                            hasEmptyCell = true;
                            break;
                        }
                    }
                    if (hasEmptyCell) break;
                }
                
                if (!hasEmptyCell) {
                    // 检查是否还能移动
                    let canMove = false;
                    for (let i = 0; i < 4; i++) {
                        for (let j = 0; j < 4; j++) {
                            if (j < 3 && this.grid[i][j] === this.grid[i][j + 1]) {
                                canMove = true;
                                break;
                            }
                            if (i < 3 && this.grid[i][j] === this.grid[i + 1][j]) {
                                canMove = true;
                                break;
                            }
                        }
                        if (canMove) break;
                    }
                    
                    if (!canMove) {
                        this.gameState = 'over';
                        this.showMessage('游戏结束', '没有更多可移动的方块了！');
                    }
                }
                
                // 检查成就
                this.checkAchievements();
            }
            
            checkAchievements() {
                const maxTile = Math.max(...this.grid.flat());
                if (maxTile >= 512) this.unlockAchievement(512);
                if (maxTile >= 1024) this.unlockAchievement(1024);
                if (maxTile >= 2048) this.unlockAchievement(2048);
            }
            
            unlockAchievement(value) {
                const element = document.getElementById(`achievement${value}`);
                if (element && element.style.opacity === '0.3') {
                    element.style.opacity = '1';
                    this.showNotification(`成就解锁：达到${value}！`);
                }
            }
            
            showNotification(message) {
                const notification = document.createElement('div');
                notification.className = 'fixed top-4 right-4 bg-yellow-500 text-white px-4 py-2 rounded-lg shadow-lg z-50';
                notification.innerHTML = `<i class="fas fa-trophy mr-2"></i>${message}`;
                
                document.body.appendChild(notification);
                
                setTimeout(() => {
                    notification.remove();
                }, 3000);
            }
            
            updateDisplay() {
                // 更新分数
                document.getElementById('score').textContent = this.score;
                document.getElementById('moves').textContent = this.moves;
                
                // 更新最高分
                if (this.score > this.best) {
                    this.best = this.score;
                    localStorage.setItem('2048-best', this.best);
                }
                document.getElementById('best').textContent = this.best;
                
                // 更新游戏统计
                const maxTile = Math.max(...this.grid.flat());
                const emptyCells = this.grid.flat().filter(cell => cell === 0).length;
                
                document.getElementById('maxTile').textContent = maxTile;
                document.getElementById('emptyCells').textContent = emptyCells;
                
                // 更新方块显示
                this.updateTiles();
            }
            
            updateTiles() {
                const container = document.getElementById('tileContainer');
                container.innerHTML = '';
                
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        if (this.grid[i][j] !== 0) {
                            const tile = document.createElement('div');
                            tile.className = `tile tile-${this.grid[i][j]}`;
                            if (this.grid[i][j] > 2048) {
                                tile.className = 'tile tile-super';
                            }
                            tile.textContent = this.grid[i][j];
                            tile.style.left = (j * 122) + 'px';
                            tile.style.top = (i * 122) + 'px';
                            container.appendChild(tile);
                        }
                    }
                }
            }
            
            showMessage(title, text) {
                document.getElementById('messageTitle').textContent = title;
                document.getElementById('messageText').textContent = text;
                
                const messageDiv = document.getElementById('gameMessage');
                messageDiv.className = `game-message ${this.gameState === 'won' ? 'game-won' : 'game-over'}`;
                messageDiv.style.display = 'flex';
            }
            
            hideMessage() {
                document.getElementById('gameMessage').style.display = 'none';
            }
            
            saveState() {
                this.history.push({
                    grid: this.grid.map(row => [...row]),
                    score: this.score,
                    moves: this.moves
                });
                
                // 只保留最近10步
                if (this.history.length > 10) {
                    this.history.shift();
                }
            }
            
            undoMove() {
                if (this.history.length > 1) {
                    this.history.pop(); // 移除当前状态
                    const previousState = this.history[this.history.length - 1];
                    
                    this.grid = previousState.grid.map(row => [...row]);
                    this.score = previousState.score;
                    this.moves = previousState.moves;
                    
                    this.gameState = 'playing';
                    this.hideMessage();
                    this.updateDisplay();
                }
            }
            
            newGame() {
                this.hideMessage();
                this.stopTimer();
                this.init();
                this.updateDisplay();
            }
            
            togglePause() {
                if (this.gameState === 'playing') {
                    this.gameState = 'paused';
                    this.isPaused = true;
                    this.stopTimer();
                    document.getElementById('pauseBtn').innerHTML = '<i class="fas fa-play mr-2"></i>继续';
                    this.showMessage('游戏暂停', '点击继续按钮恢复游戏');
                } else if (this.gameState === 'paused') {
                    this.gameState = 'playing';
                    this.isPaused = false;
                    this.startTimer();
                    document.getElementById('pauseBtn').innerHTML = '<i class="fas fa-pause mr-2"></i>暂停';
                    this.hideMessage();
                }
            }
            
            startTimer() {
                this.gameTimer = setInterval(() => {
                    if (!this.isPaused && this.startTime) {
                        const elapsed = Math.floor((Date.now() - this.startTime) / 1000);
                        const minutes = Math.floor(elapsed / 60);
                        const seconds = elapsed % 60;
                        document.getElementById('gameTime').textContent = 
                            `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
                    }
                }, 1000);
            }
            
            stopTimer() {
                if (this.gameTimer) {
                    clearInterval(this.gameTimer);
                    this.gameTimer = null;
                }
            }
        }
        
        // 全局游戏实例
        let game;
        
        // 初始化游戏
        document.addEventListener('DOMContentLoaded', function() {
            game = new Game2048();
        });
        
        // 全局函数
        function newGame() {
            game.newGame();
        }
        
        function undoMove() {
            game.undoMove();
        }
        
        function togglePause() {
            game.togglePause();
        }
        
        function move(direction) {
            game.move(direction);
        }
    </script>
</body>
</html>